import { defineStore } from 'pinia';
import SockJS from 'sockjs-client/dist/sockjs.min.js';
import Stomp from 'stompjs';
import { ElNotification, ElMessage } from 'element-plus';
import { NOTIFICATION_TYPE } from '@/constants/common/notification-type';
import { useUserStore } from '@/store/modules/user';
import { showNotification } from '@/utils/message';
import { ref, reactive, computed } from 'vue';

// WebSocket 配置
const SOCKET_CONFIG = {
  // 线上环境
  PRODUCTION_URL: 'http://101.201.32.10711:8989/ws',
  // 本地环境
  LOCAL_URL: '/ws',
  // 重连配置
  RECONNECT_ATTEMPTS: 5,
  RECONNECT_INTERVAL: 3000,
  // 心跳配置
  HEARTBEAT_INTERVAL: 30000,
  // 消息配置
  MAX_MESSAGE_HISTORY: 100
};

// 通知消息接口
interface NotificationMessage {
  id: string;
  type: NOTIFICATION_TYPE;
  sender: string;
  content: string;
  avatar?: string;
  link?: string;
  isRead: boolean;
  createTime: string;
  receiverId?: number;
  data?: NotificationMessage;
}

// WebSocket 消息接口
interface WebSocketMessage {
  type: string;
  data: NotificationMessage;
  timestamp: string;
}

let stompClient: Stomp.Client;
let reconnectAttempts = 0;
let heartbeatTimer: NodeJS.Timeout | null = null;
let reconnectTimer: NodeJS.Timeout | null = null;

/**
 * WebSocket连接管理Store
 * @description 用于管理WebSocket连接、消息处理和通知显示
 * @author 系统
 * @version 1.0.0
 * @since 2024-01-01
 */
export const useSocketStore = defineStore(
  'socketState',
  () => {
    /**
     * WebSocket连接状态
     * @type {import('vue').Ref<boolean>}
     * @description 是否已连接到WebSocket服务器
     */
    const isConnectWebSocket = ref(false);

    /**
     * 连接状态
     * @type {import('vue').Ref<'connected' | 'connecting' | 'disconnected' | 'error'>}
     * @description WebSocket连接的详细状态
     */
    const connectionStatus = ref<'connected' | 'connecting' | 'disconnected' | 'error'>(
      'disconnected'
    );

    /**
     * 消息历史记录
     * @type {import('vue').Ref<NotificationMessage[]>}
     * @description 存储所有收到的通知消息
     */
    const messageHistory = ref<NotificationMessage[]>([]);

    /**
     * 未读消息数量
     * @type {import('vue').Ref<number>}
     * @description 当前未读的通知消息数量
     */
    const unreadCount = ref(0);

    /**
     * 最后连接时间
     * @type {import('vue').Ref<string | null>}
     * @description 最后一次成功连接的时间戳
     */
    const lastConnectedTime = ref<string | null>(null);

    /**
     * 连接错误信息
     * @type {import('vue').Ref<string | null>}
     * @description 连接失败时的错误信息
     */
    const connectionError = ref<string | null>(null);

    /**
     * 重连次数
     * @type {import('vue').Ref<number>}
     * @description 当前重连尝试的次数
     */
    const reconnectCount = ref(0);

    /**
     * 通知刷新标志
     * @type {import('vue').Ref<number>}
     * @description 用于触发通知列表刷新的计数器
     */
    const notificationRefreshFlag = ref(0);
    /**
     * 连接状态文本
     * @type {import('vue').ComputedRef<string>}
     * @description 连接状态的中文显示文本
     */
    const connectionStatusText = computed(() => {
      const statusMap = {
        connected: '已连接',
        connecting: '连接中',
        disconnected: '未连接',
        error: '连接错误'
      };
      return statusMap[connectionStatus.value];
    });

    /**
     * 未读消息列表
     * @type {import('vue').ComputedRef<NotificationMessage[]>}
     * @description 过滤出的所有未读消息
     */
    const unreadMessages = computed(() => messageHistory.value.filter(msg => !msg.isRead));

    /**
     * 最新消息列表
     * @type {import('vue').ComputedRef<NotificationMessage[]>}
     * @description 最近收到的10条消息
     */
    const latestMessages = computed(() => messageHistory.value.slice(0, 10));
    /**
     * 获取WebSocket URL
     * @returns {string} WebSocket服务器URL
     * @description 根据环境返回对应的WebSocket连接地址
     */
    const getSocketUrl = () => {
      const userStore = useUserStore();
      // 根据环境返回不同的URL
      return import.meta.env.PROD ? SOCKET_CONFIG.PRODUCTION_URL : SOCKET_CONFIG.LOCAL_URL;
    };

    /**
     * 广播消息
     * @param {string} topicMessage - 广播消息内容
     * @description 向所有连接的客户端发送广播消息
     */
    const sendToAll = (topicMessage: string) => {
      if (stompClient && stompClient.connected) {
        stompClient.send('/app/sendToAll', {}, topicMessage);
      } else {
        ElMessage.warning('WebSocket未连接，无法发送消息');
      }
    };

    /**
     * 发送给指定用户
     * @param {string} receiver - 接收者用户名
     * @param {string} queueMessage - 私信消息内容
     * @description 向特定用户发送私信消息
     */
    const sendToUser = (receiver: string, queueMessage: string) => {
      if (stompClient && stompClient.connected) {
        stompClient.send(`/app/sendToUser/${receiver}`, {}, queueMessage);
      } else {
        ElMessage.warning('WebSocket未连接，无法发送消息');
      }
    };

    /**
     * 创建WebSocket连接
     * @description 建立与WebSocket服务器的连接
     */
    const connectWebSocket = () => {
      const userStore = useUserStore();

      // 如果已经连接，直接返回
      if (isConnectWebSocket.value && stompClient?.connected) {
        return;
      }

      // 如果正在连接，直接返回
      if (connectionStatus.value === 'connecting') {
        return;
      }

      // 更新连接状态
      connectionStatus.value = 'connecting';
      connectionError.value = null;

      try {
        const socketUrl = getSocketUrl();
        console.log('连接WebSocket:', socketUrl);

        const socket = new SockJS(socketUrl);

        stompClient = Stomp.over(socket);

        // 设置调试模式（开发环境）
        if (import.meta.env.DEV) {
          stompClient.debug = console.log;
        } else {
          stompClient.debug = () => {}; // 使用空函数而不是null
        }

        // 准备连接头
        const connectHeaders = {
          // 修改认证头格式为 Bearer token
          Authorization: userStore.token,
          'heart-beat': '30000,30000' // 设置心跳
        };

        console.log('连接头:', connectHeaders);

        stompClient.connect(
          connectHeaders,
          () => {
            onConnectSuccess();
          },
          error => {
            onConnectError(error);
          }
        );
      } catch (error) {
        onConnectError(error);
      }
    };

    /**
     * 连接成功回调
     * @description WebSocket连接成功后的处理逻辑
     */
    const onConnectSuccess = () => {
      isConnectWebSocket.value = true;
      connectionStatus.value = 'connected';
      lastConnectedTime.value = new Date().toISOString();
      connectionError.value = null;
      reconnectCount.value = 0;
      reconnectAttempts = 0;

      const userStore = useUserStore();
      const userId = userStore.userInfo.id;

      console.log('=== WebSocket连接成功 ===');
      console.log('当前用户ID:', userId);
      console.log('用户信息:', userStore.userInfo);
      console.log('STOMP客户端状态:', stompClient.connected);
      console.log('STOMP客户端连接信息:', stompClient);

      // 订阅个人通知队列
      console.log('正在订阅个人通知队列: /user/queue/notifications');
      const notificationSubscription = stompClient.subscribe(
        `/user/${userId}/queue/notifications`,
        message => {
          console.log('=== 收到通知订阅消息 ===');
          console.log('消息头:', message.headers);
          console.log('消息体:', message.body);
          console.log('消息ID:', (message.headers as any)['message-id']);
          console.log('订阅ID:', (message.headers as any)['subscription']);
          handleNotificationMessage(message);
        }
      );

      console.log('通知订阅已建立:', notificationSubscription);
      console.log('订阅ID:', notificationSubscription.id);

      // 订阅系统广播
      console.log('正在订阅系统广播: /topic/system');
      const systemSubscription = stompClient.subscribe('/topic/system', message => {
        console.log('=== 收到系统订阅消息 ===');
        console.log('消息头:', message.headers);
        console.log('消息体:', message.body);
        handleSystemMessage(message);
      });

      console.log('系统订阅已建立:', systemSubscription);

      // 订阅全局通知
      console.log('正在订阅全局通知: /topic/notice');
      const globalSubscription = stompClient.subscribe('/topic/notice', message => {
        console.log('=== 收到全局通知订阅消息 ===');
        console.log('消息头:', message.headers);
        console.log('消息体:', message.body);
        handleGlobalNotice(message);
      });

      console.log('全局通知订阅已建立:', globalSubscription);

      // 启动心跳检测
      startHeartbeat();

      // 触发连接成功事件
      window.dispatchEvent(new CustomEvent('websocketConnected'));

      console.log('=== WebSocket初始化完成 ===');
    };

    /**
     * 连接错误回调
     * @param {any} error - 错误对象
     * @description WebSocket连接失败后的处理逻辑
     */
    const onConnectError = (error: any) => {
      isConnectWebSocket.value = false;
      connectionStatus.value = 'error';
      connectionError.value = error?.message || '连接失败';

      console.error('WebSocket连接失败:', error);

      // 停止心跳
      stopHeartbeat();

      // 尝试重连
      attemptReconnect();
    };

    /**
     * 尝试重连
     * @description 在连接失败后尝试重新连接
     */
    const attemptReconnect = () => {
      if (reconnectAttempts >= SOCKET_CONFIG.RECONNECT_ATTEMPTS) {
        connectionStatus.value = 'error';
        connectionError.value = '重连次数已达上限，请手动重连';
        ElMessage.error('WebSocket重连失败，请刷新页面重试');
        return;
      }

      reconnectAttempts++;
      reconnectCount.value = reconnectAttempts;

      console.log(`尝试重连 (${reconnectAttempts}/${SOCKET_CONFIG.RECONNECT_ATTEMPTS})`);

      // 清除之前的重连定时器
      if (reconnectTimer) {
        clearTimeout(reconnectTimer);
      }

      // 延迟重连
      reconnectTimer = setTimeout(() => {
        connectWebSocket();
      }, SOCKET_CONFIG.RECONNECT_INTERVAL);
    };

    /**
     * 启动心跳检测
     * @description 开始发送心跳包以保持连接活跃
     */
    const startHeartbeat = () => {
      stopHeartbeat();

      heartbeatTimer = setInterval(() => {
        if (stompClient && stompClient.connected) {
          // 发送心跳包
          stompClient.send(
            '/app/heartbeat',
            {},
            JSON.stringify({
              timestamp: new Date().toISOString(),
              userId: useUserStore().userInfo.id
            })
          );
        } else {
          // 心跳失败，尝试重连
          onConnectError(new Error('心跳检测失败'));
        }
      }, SOCKET_CONFIG.HEARTBEAT_INTERVAL);
    };

    /**
     * 停止心跳检测
     * @description 停止心跳检测定时器
     */
    const stopHeartbeat = () => {
      if (heartbeatTimer) {
        clearInterval(heartbeatTimer);
        heartbeatTimer = null;
      }
    };

    /**
     * 处理通知消息
     * @param {any} message - 原始消息对象
     * @description 处理收到的通知类型消息
     */
    const handleNotificationMessage = (message: any) => {
      try {
        console.log('收到原始消息:', message);
        console.log('消息体:', message.body);

        const wsMessage: WebSocketMessage = JSON.parse(message.body);
        console.log('解析后的消息:', wsMessage);

        if (wsMessage.type === 'notification') {
          const notification: NotificationMessage = wsMessage.data;
          console.log('通知数据:', notification);

          showBrowserNotification(notification);
          // 调用类型通知
          showNotification({
            title: (() => {
              switch (notification.type) {
                case NOTIFICATION_TYPE.SYSTEM:
                  return '系统通知';
                case NOTIFICATION_TYPE.COMMENT:
                  return '评论通知';
                case NOTIFICATION_TYPE.LIKE:
                  return '点赞通知';
                default:
                  return '消息通知';
              }
            })(),
            content: String(notification.content),
            type: (() => {
              switch (notification.type) {
                case NOTIFICATION_TYPE.SYSTEM:
                  return 'info';
                case NOTIFICATION_TYPE.COMMENT:
                  return 'success';
                case NOTIFICATION_TYPE.LIKE:
                  return 'warning';
                default:
                  return 'info';
              }
            })(),
            duration: 4000,
            showDetail: true
          });
          // 每次有新消息自增，然后被监听的notificationRefreshFlag，触发刷新通知列表
          notificationRefreshFlag.value++;

          console.log('通知消息处理完成');
        } else {
          console.log('未知消息类型:', wsMessage.type);
        }
      } catch (error) {
        console.error('解析通知消息失败:', error);
        console.error('原始消息:', message);
      }
    };

    /**
     * 处理系统消息
     * @param {any} message - 原始消息对象
     * @description 处理收到的系统广播消息
     */
    const handleSystemMessage = (message: any) => {
      try {
        const wsMessage: WebSocketMessage = JSON.parse(message.body);

        ElNotification({
          title: '系统消息',
          message:
            typeof wsMessage.data === 'object' && wsMessage.data.content
              ? String(wsMessage.data.content)
              : String(wsMessage.data),
          type: 'info',
          duration: 5000
        });

        console.log('收到系统消息:', wsMessage);
      } catch (error) {
        console.error('解析系统消息失败:', error);
      }
    };

    /**
     * 处理全局通知
     * @param {any} message - 原始消息对象
     * @description 处理收到的全局通知消息
     */
    const handleGlobalNotice = (message: any) => {
      try {
        ElNotification({
          title: '全局通知',
          message: message.body,
          type: 'success',
          duration: 3000
        });

        console.log('收到全局通知:', message.body);
      } catch (error) {
        console.error('处理全局通知失败:', error);
      }
    };

    /**
     * 添加消息到历史记录
     * @param {NotificationMessage} message - 通知消息对象
     * @description 将消息添加到历史记录并限制最大数量
     */
    const addMessageToHistory = (message: NotificationMessage) => {
      // 限制历史记录数量
      if (messageHistory.value.length >= SOCKET_CONFIG.MAX_MESSAGE_HISTORY) {
        messageHistory.value.pop();
      }

      messageHistory.value.unshift(message);

      // 保存到本地存储
      saveMessageHistory();
    };

    /**
     * 保存消息历史到本地存储
     * @description 将消息历史保存到localStorage
     */
    const saveMessageHistory = () => {
      try {
        localStorage.setItem('socket_message_history', JSON.stringify(messageHistory.value));
      } catch (error) {
        console.error('保存消息历史失败:', error);
      }
    };

    /**
     * 从本地存储加载消息历史
     * @description 从localStorage加载之前保存的消息历史
     */
    const loadMessageHistory = () => {
      try {
        const history = localStorage.getItem('socket_message_history');
        if (history) {
          messageHistory.value = JSON.parse(history);
          updateUnreadCount();
        }
      } catch (error) {
        console.error('加载消息历史失败:', error);
      }
    };

    /**
     * 更新未读消息数量
     * @description 重新计算未读消息数量
     */
    const updateUnreadCount = () => {
      unreadCount.value = messageHistory.value.filter(msg => !msg.isRead).length;
    };

    /**
     * 标记消息为已读
     * @param {string} messageId - 消息ID
     * @description 将指定消息标记为已读状态
     */
    const markMessageAsRead = (messageId: string) => {
      const message = messageHistory.value.find(msg => msg.id === messageId);
      if (message && !message.isRead) {
        message.isRead = true;
        updateUnreadCount();
        saveMessageHistory();
      }
    };

    /**
     * 标记所有消息为已读
     * @description 将所有消息标记为已读状态
     */
    const markAllMessagesAsRead = () => {
      messageHistory.value.forEach(msg => {
        msg.isRead = true;
      });
      updateUnreadCount();
      saveMessageHistory();
    };

    /**
     * 清空消息历史
     * @description 清空所有消息历史记录
     */
    const clearMessageHistory = () => {
      messageHistory.value = [];
      unreadCount.value = 0;
      saveMessageHistory();
    };

    /**
     * 显示浏览器通知
     * @param {NotificationMessage} notification - 通知消息对象
     * @description 在浏览器中显示桌面通知
     */
    const showBrowserNotification = (notification: NotificationMessage) => {
      // 检查浏览器通知权限
      if (Notification.permission === 'granted') {
        new Notification(notification.sender, {
          body: notification.content,
          icon: notification.avatar || '/favicon.ico',
          tag: notification.id,
          requireInteraction: false
        });
      } else if (Notification.permission === 'default') {
        // 请求通知权限
        Notification.requestPermission().then(permission => {
          if (permission === 'granted') {
            showBrowserNotification(notification);
          }
        });
      }
    };

    /**
     * 手动重连
     * @description 手动触发WebSocket重新连接
     */
    const manualReconnect = () => {
      disconnectWebSocket();
      reconnectAttempts = 0;
      reconnectCount.value = 0;
      setTimeout(() => {
        connectWebSocket();
      }, 1000);
    };

    /**
     * 断开连接
     * @description 主动断开WebSocket连接
     */
    const disconnectWebSocket = () => {
      if (stompClient && stompClient.connected) {
        stompClient.disconnect(() => {
          isConnectWebSocket.value = false;
          connectionStatus.value = 'disconnected';
          stopHeartbeat();

          // 清除重连定时器
          if (reconnectTimer) {
            clearTimeout(reconnectTimer);
            reconnectTimer = null;
          }

          console.log('WebSocket已断开连接');
        });
      }
    };

    /**
     * 获取连接状态信息
     * @returns {Object} 连接状态信息对象
     * @description 获取当前的WebSocket连接状态信息
     */
    const getConnectionInfo = () => ({
      isConnected: isConnectWebSocket.value,
      status: connectionStatus.value,
      statusText: connectionStatusText.value,
      lastConnectedTime: lastConnectedTime.value,
      connectionError: connectionError.value,
      reconnectCount: reconnectCount.value,
      unreadCount: unreadCount.value,
      messageCount: messageHistory.value.length
    });

    /**
     * 测试连接和订阅
     * @description 测试WebSocket连接状态和订阅信息
     */
    const testConnection = () => {
      console.log('=== 测试WebSocket连接 ===');
      console.log('连接状态:', connectionStatus.value);
      console.log('是否已连接:', isConnectWebSocket.value);
      console.log('STOMP客户端:', stompClient);
      console.log('STOMP连接状态:', stompClient?.connected);

      if (stompClient && stompClient.connected) {
        console.log('STOMP订阅列表:', (stompClient as any).subscriptions);
        console.log('STOMP连接头:', (stompClient as any).connectHeaders);
      }

      const userStore = useUserStore();
      console.log('当前用户:', userStore.userInfo);
      console.log('用户Token:', userStore.token);
    };

    // 返回所有状态和方法
    return {
      // 状态
      isConnectWebSocket,
      connectionStatus,
      connectionError,
      lastConnectedTime,
      reconnectCount,
      messageHistory,
      unreadCount,
      notificationRefreshFlag,

      // getters
      connectionStatusText,
      unreadMessages,
      latestMessages,

      // 方法
      getSocketUrl,
      sendToAll,
      sendToUser,
      connectWebSocket,
      onConnectSuccess,
      onConnectError,
      attemptReconnect,
      startHeartbeat,
      stopHeartbeat,
      handleNotificationMessage,
      handleSystemMessage,
      handleGlobalNotice,
      addMessageToHistory,
      saveMessageHistory,
      loadMessageHistory,
      updateUnreadCount,
      markMessageAsRead,
      markAllMessagesAsRead,
      clearMessageHistory,
      showBrowserNotification,
      manualReconnect,
      disconnectWebSocket,
      getConnectionInfo,
      testConnection
    };
  },
  {
    // 进行持久化存储
    persist: {
      // 本地存储的名称
      key: 'socketState',
      // 保存的位置
      storage: window.localStorage,
      // 指定要持久化的字段
      paths: ['messageHistory', 'unreadCount', 'lastConnectedTime']
    }
  }
);
